package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.dto.SetmealDto;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.exception.CustomException;
import com.itheima.reggie.mapper.SetMealDishMapper;
import com.itheima.reggie.mapper.SetMealMapper;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.SetMealDishService;
import com.itheima.reggie.service.SetMealService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class SetMealServiceImpl implements SetMealService {

    @Autowired
    private SetMealMapper mapper;

    @Autowired
    private SetMealDishService setMealDishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SetMealDishMapper setMealDishMapper;


    /**
     * 删除套餐（包含单个删除和批量删除）
     * 1. 不能直接就去删除套餐数据，要看套餐的状态是否是停售状态
     * 2. 如果有套餐是启售状态，那么直接抛出异常，禁止删除！
     * 3. 只有当所有的要删除的套餐都是停售状态，那么才允许去做删除操作
     * 3.1 由于套餐数据是保存在两张表里面： 套餐表 和 套餐菜品表
     * 3.2 所以要删除一个套餐，就必须要删除两张表
     *
     * @param ids
     * @return
     */
    @Override
    public int delete(List<Long> ids) { // 1, 3, 5   启售状态值： 1
        // select count(*) from setmeal where status = 1 and id in ( 1 , 3,  5 ) ;
        //1. 先查询这一批id里面有没有套餐是启售状态，如果是，那么直接抛出异常！。
        LambdaQueryWrapper<Setmeal> qw = new LambdaQueryWrapper<>();
        qw.eq(Setmeal::getStatus, 1); //查询状态为启售状态
        qw.in(Setmeal::getId, ids);

        //1.1 查询数量： 在这些id里面，启售的数量有几个
        int count = mapper.selectCount(qw);
        if (count > 0) {
            throw new CustomException("套餐包含启售状态，禁止删除！");
        }

        //2. 如果到了这里，就表示这些套餐都是停售状态，那么直接删除即可。

        //2.1 先删除套餐表
        int row = mapper.deleteBatchIds(ids);

        //2.2 后删除套餐菜品表
        for (Long id : ids) {
            setMealDishService.deleteBySetmealId(id);
        }

        return row;
    }

    /**
     * 分页查询套餐
     * 1. 不能认为是查询套餐表得到结果之后，直接返回。
     * 2. 因为Controller需要的是 IPage<SetMealDto> , 去查询套餐表得到的是：IPage<SetMeal>
     * 3. service 作为中间层，此时就需要自己去封装IPage<SetMealDto> 向上返回！
     *
     * @param pageParam
     * @return
     */
    @Override
    public IPage<SetmealDto> findPage(PageParam pageParam) {

        //1. 先去查询套餐表，得到分页数据。
        IPage<Setmeal> p = new Page<>(pageParam.getPage(), pageParam.getPageSize());

        //1.1 设置搜索条件
        LambdaQueryWrapper<Setmeal> qw = new LambdaQueryWrapper<>();
        qw.like(pageParam.getName() != null, Setmeal::getName, pageParam.getName());

        //1.2 执行查询
        mapper.selectPage(p, qw);

        //2. 创建IPage<SetmealDto>
        IPage<SetmealDto> dtoIPage = new Page<>();

        //2.1 设置total
        dtoIPage.setTotal(p.getTotal());

        //2.2 设置records;

        //2.2.1 遍历集合
        List<SetmealDto> dtoList = p.getRecords().stream().map(setmeal -> {

            //a. 创建一个SetMealDto
            SetmealDto dto = new SetmealDto();

            //b. 把setmeal拷贝到dto上
            BeanUtils.copyProperties(setmeal, dto);

            //c. 查询套餐的数据，设置分类的名称
            Category category = categoryService.findById(setmeal.getCategoryId());
            dto.setCategoryName(category.getName());
            dto.setSetmealDishes(setMealDishService.findByStemealId(setmeal.getId()));
            //d. 返回dto 以便这些dto能够装到后面产出的集合里面
            return dto;
        }).collect(Collectors.toList());

        dtoIPage.setRecords(dtoList);

        return dtoIPage;
    }

    /**
     * 新增套餐
     * 1. 套餐的数据包含两部分： 套餐的基本数据  和 套餐包含的菜品数据
     * 2. 这个新增动作，需要操作两张表： 套餐表  和  套餐菜品表
     * 3. 需要往两张表里面执行添加操作，
     * 3.1 先往套餐表里面添加数据
     * 3.2 再往套餐菜品表里面添加数据
     *
     * @param setmealDto
     * @return
     */
    @Override
    public int add(SetmealDto setmealDto) {

        //1. 先往套餐表添加基本数据
        int row = mapper.insert(setmealDto);

        //2. 往套餐菜品表添加数据
        List<SetmealDish> dishList = setmealDto.getSetmealDishes();

        int row2 = 0;
        if (dishList != null && dishList.size() > 0) {
            for (SetmealDish setmealDish : dishList) {

                //设置这个菜品属于哪一个套餐
                setmealDish.setSetmealId(setmealDto.getId());

                row2 += setMealDishService.add(setmealDish);
            }
            return row > 0 && row2 == dishList.size() ? 1 : 0;
        }
        return row;
    }

    /**
     * 根据分类id来查询套餐表，查询这个分类在套餐表里面的总数
     *
     * @param categoryId
     * @return
     */
    @Override
    public int findCountByCategoryId(long categoryId) {

        //1. 创建条件对象
        LambdaQueryWrapper<Setmeal> qw = new LambdaQueryWrapper<>();
        qw.eq(Setmeal::getCategoryId, categoryId);

        //2. 执行查询
        return mapper.selectCount(qw);
    }

    /**
     * 根据分类id和装填来查询套餐数据
     *
     * @param categoryId
     * @param status
     * @return
     */
    @Override
    public List<Setmeal> findCategoryById(Long categoryId, Integer status) {

        //创造条件  select * from setmeal where categoryId = ? and status = ?

        //如果没有条件，就变成查询所有 ：   select * from setmeal  动态SQL
        LambdaQueryWrapper<Setmeal> qw = new LambdaQueryWrapper<>();
        qw.eq(categoryId != null, Setmeal::getCategoryId, categoryId);
        qw.eq(status != null, Setmeal::getStatus, status);


        //执行查询
        return mapper.selectList(qw);
    }

    @Override
    public int updateStatus(List<Long> ids, Integer status) {
        List<Setmeal> setmeals = mapper.selectBatchIds(ids);
        int rows = 0;
        for (Setmeal setmeal : setmeals) {
            setmeal.setStatus(status);
            rows += mapper.updateById(setmeal);
        }
        if (rows == setmeals.size()) {
            return 1;
        }
        return 0;
    }

    @Override
    public int upadateSetmeal(SetmealDto setmealDto) {
        int rows = mapper.updateById(setmealDto);
        List<SetmealDish> list = setmealDto.getSetmealDishes();
        setMealDishService.deleteBySetmealId(setmealDto.getId());
        int count = 0;
        for (SetmealDish setmealDish : list) {
            setmealDish.setSetmealId(setmealDto.getId());
            setmealDish.setIsDeleted(0);
            count  += setMealDishService.add(setmealDish);
        }
        return rows>0&&count ==list.size()?1:0;
    }


}
